// 串口屏显示
#include "USART_HMI.h"
#include "string.h"
#include <stdio.h>
#include <stdlib.h>
#include "CalibrationSensor.h"
#include "Battery.h"
#include "RingFIFO.h"

//
#include "stm32f1xx_hal.h"
#include "dma.h"
#include "usart.h"

#define USE_UART huart3
#define TIMEOUT 1000
//

#define RawDataStringBufferSize 128
static uint8_t RawDataString[RawDataStringBufferSize] = {0}; // 接收缓冲区
static uint8_t RawDataStringFIFOBuffer[RawDataStringBufferSize] = {0}; // 环形缓冲区数据
static RingFIFO_t RawDataStringFIFO; // 环形缓冲区

static HMIStatus_e HMIStatus = HMI_Stop;
static float Data = 0;

#define TransmitBufferSize 1024
static uint16_t TransmitBufferEnd = 0;
static uint8_t TransmitBuffer[TransmitBufferSize] = {0};

static void UARTTransmit(uint8_t *data, uint16_t size)
{
    HAL_UART_Transmit_DMA(&USE_UART, (uint8_t *)data, size);
}

static void UARTReceive()
{
    HAL_UARTEx_ReceiveToIdle_DMA(&USE_UART, RawDataStringFIFOBuffer, RawDataStringBufferSize);
    __HAL_DMA_DISABLE_IT(USE_UART.hdmarx, DMA_IT_HT);
}

void TransmitBufferAdd(char *str)
{
    uint16_t size = strlen(str);
    if ((TransmitBufferEnd + size) % TransmitBufferSize == 1) // 缓冲区满
        return;
    memcpy(&TransmitBuffer[TransmitBufferEnd], str, size); // 复制到缓冲区
    TransmitBufferEnd += size;
    TransmitBufferEnd %= TransmitBufferSize;
}

void HMIInit(void)
{
    // HMISetTargetPressuer(0);
    // HAL_Delay(10);
    // HMISetNowPressure(0);
    // HAL_Delay(10);
    // HMISetNowVoltage(0);
    // HAL_Delay(10);
    // HMISetStatus(GoZero);
    HMIOpenValve();
    RingFIFO_Init(&RawDataStringFIFO, RawDataStringFIFOBuffer, RawDataStringBufferSize); // 初始化环形缓冲区
    UARTReceive();
}

float HMIGetData(void)
{
    return Data;
}

HMIStatus_e HMIGetStatus(void)
{
    if (BatteryGetProtection())
    {
        HMIStatus = HMI_Stop;
        HMILowVoltage();
    }
    return HMIStatus;
}

void HMIGetCallback(uint8_t Size)
{
    // 接收回调函数，Size为接收到的数据长度
    if (Size == 0) // 没有接收到数据
    {
        return; // 直接返回
    }
    // 由于DMA已经将数据写入到FIFO中，在此处只需要更新索引即可
    // 开启DMA循环接收后，huart->RxXferCount的数据不会被清空，也就是累计的接收量，将其直接作为头索引使用
    RingFIFO_SetHeadIndex(&RawDataStringFIFO, Size); // 更新环形缓冲区头索引
    // UARTReceive(); // 使用循环接收，不需要再次调用接收函数
}

/**
 * @brief HMI处理回调函数
 *
 */
void HMIProcessCallback(void)
{
    // 对HMI发送回来的数据进行解包处理

    // 将环形缓冲区数据复制到RawDataString中
    uint8_t len = RingFIFO_Read(&RawDataStringFIFO, RawDataString, RingFIFO_Size(&RawDataStringFIFO));
    // RingFIFO_SetZero(&RawDataStringFIFO); // 清空环形缓冲区，仅在debug时调用以查看当前接收到的消息位置
    if (len < 5) // 数据长度小于5，无法解析
    {
        return; // 直接返回
    }


    // 旧协议，弃用
    // if (RawDataString[0] == 0xAA && RawDataString[3] == 0x55) // 头尾校验
    // {
    //     Data = (float)((RawDataString[2] << 8) | (RawDataString[1])) / 1000;
    // }
    // HMISetTargetPressuer(Data);

    for (uint8_t i = 0; i < len; i++)
    {
        if (RawDataString[i] == 0xAA && i <= len - 5) // 自定帧头
        {
            if (RawDataString[i + 0] == 0xAA && RawDataString[i + 4] == 0x55) // 头尾校验
            {
                switch (RawDataString[i + 1])
                {
                case 0:
                    // 停止
                    HMIStatus = HMI_Stop;
                    if ((RawDataString[i + 2] + RawDataString[i + 3]) == 0)
                    {
                        SetCurrentSensorType(0);
                    }
                    break;
                case 1:
                    // 仪表模式
                    if (HMIStatus == HMI_Stop)
                    {
                        HMIStatus = HMI_Model;
                    }
                    SetCurrentSensorType(RawDataString[i + 2]);
                    break;
                case 2:
                    // 手动模式
                    if (HMIStatus == HMI_Stop)
                    {
                        HMIStatus = HMI_Manual;
                    }
                    SetCurrentSensorType(0);
                    Data = (float)(((uint16_t)RawDataString[i + 3] << 8) | (RawDataString[i + 2])) / 1000;
                    break;
                case 3:
                    // 回零模式
                    if (RawDataString[i + 2] == 0x00) //
                    {
                        if (HMIStatus == HMI_Stop)
                        {
                            HMIStatus = HMI_GoZero;
                        }
                    }
                case 4:
                    // 换液模式
                    if (RawDataString[i + 2] == 0x00) //
                    {
                        if (HMIStatus == HMI_Stop)
                        {
                            HMIStatus = HMI_Drain;
                        }
                    }
                case 5:
                    // 排气模式
                    if (RawDataString[i + 2] == 0x00) // 排气前流程，先回零
                    {
                        if (HMIStatus == HMI_Stop)
                        {
                            HMIStatus = HMI_PreFill;
                        }
                    }
                    else if (RawDataString[i + 2] == 0x01) // 排气后流程，加压排气
                    {
                        if (HMIStatus == HMI_Stop)
                        {
                            HMIStatus = HMI_Fill;
                        }
                    }
                default:
                    // 其他数据包
                    continue;
                }
            }
        }
    }
}

void HMITransmitCallback(void)
{
    if (TransmitBufferEnd != 0) // 有数值
    {
        UARTTransmit((uint8_t *)TransmitBuffer, TransmitBufferEnd);
        TransmitBufferEnd = 0;
    }
}

/**
 * @brief HMI设置目标压力
 *
 * @param data
 */
void HMISetTargetPressuer(float data)
{
    static char str[32] = {0};
    int16_t set = (uint16_t)(data * 1000) % 100000;
    sprintf(str, "More.x1.val=%d\xff\xff\xff", set);
    TransmitBufferAdd(str);
}

/**
 * @brief HMI设置当前压力
 *
 * @param data
 */
void HMISetNowPressure(float data)
{
    static char str[32] = {0};
    int16_t set = (uint16_t)(data * 1000) % 100000;
    sprintf(str, "More.x2.val=%d\xff\xff\xff", set);
    TransmitBufferAdd(str);
    sprintf(str, "Set.x6.val=%d\xff\xff\xff", set);
    TransmitBufferAdd(str);
}

/**
 * @brief HMI设置当前电压，在手动模式下使用
 *
 * @param data
 */
void HMISetNowVoltage(float data)
{
    static char str[32] = {0};
    int16_t set = (uint16_t)(data * 1000) % 10000;
    sprintf(str, "More.x3.val=%d\xFF\xFF\xFF", set);
    TransmitBufferAdd(str);
}

/**
 * @brief HMI设置测量值电压，在设备模式下使用
 *
 * @param index 测量点序号
 * @param data
 */
void HMISetMeasureVoltage(uint8_t index, float data)
{
    static char str[32] = {0};
    int16_t set = (uint16_t)(data * 1000) % 10000;
    sprintf(str, "Set.x%d.val=%d\xFF\xFF\xFF", index, set);
    TransmitBufferAdd(str);
}

void HMIOpenValve(void)
{
    // TransmitBufferAdd("Set.status.val=0\xff\xff\xff");
    TransmitBufferAdd("page Set\xff\xff\xff");
}

/**
 * @brief 加压完毕
 *
 */
void HMIIncreasePressureFinish(void)
{
    HMIStatus = HMI_Stop;
}

/**
 * @brief 开始回零
 *
 */
void HMIGoZeroStart(void)
{
    TransmitBufferAdd("page GoZeroLock\xff\xff\xff");
}

/**
 * @brief HMI回零完毕，解锁
 *
 */
void HMIGoZeroFinish(void)
{
    // TransmitBufferAdd("Set.status.val=2\xff\xff\xff");
    if (HMIStatus != HMI_PreFill)
        TransmitBufferAdd("page StartMeasure\xff\xff\xff");
    else
        TransmitBufferAdd("page Fill\xff\xff\xff");

    HMIStatus = HMI_Stop;
}

void HMIValveCheck(void)
{
    HMIStatus = HMI_Stop;
    TransmitBufferAdd("page ValveCheck\xff\xff\xff");
}

void HMILowVoltage(void)
{
    TransmitBufferAdd("page LowVoltage\xff\xff\xff");
}

/**
 * @brief 测量结束
 *
 */
void HMIMeasureFinish(void)
{
    HMIStatus = HMI_Stop;
    TransmitBufferAdd("Set.bt0.val=0\xff\xff\xff");
    TransmitBufferAdd("page Message\xff\xff\xff");
}

void HMIDrainFinish(void)
{
    HMIStatus = HMI_Stop;
    TransmitBufferAdd("page Drained\xff\xff\xff");
}

/**
 * @brief HMI设置显示的状态
 *
 * @param state
 */
void HMISetStatus(ControlerStatus_e state)
{
    if (HMIStatus == HMI_Manual)
    {
        switch (state)
        {
        case Ready:
            TransmitBufferAdd("More.t2.txt=\"就绪\"\xff\xff\xff");
            break;
        case GoZero:
            TransmitBufferAdd("More.t2.txt=\"回零\"\xff\xff\xff");
            break;
        case IncreasePressure:
            TransmitBufferAdd("More.t2.txt=\"加压\"\xff\xff\xff");
            break;
        case ReducePressure:
            TransmitBufferAdd("More.t2.txt=\"减压\"\xff\xff\xff");
            break;
        case Error:
            TransmitBufferAdd("More.t2.txt=\"错误\"\xff\xff\xff");
            break;
        default:
            break;
        }
    }
    else
    {
        switch (state)
        {
        case Ready:
            TransmitBufferAdd("Set.t2.txt=\"就绪\"\xff\xff\xff");
            break;
        case GoZero:
            TransmitBufferAdd("Set.t2.txt=\"回零\"\xff\xff\xff");
            break;
        case IncreasePressure:
            TransmitBufferAdd("Set.t2.txt=\"加压\"\xff\xff\xff");
            break;
        case ReducePressure:
            TransmitBufferAdd("Set.t2.txt=\"减压\"\xff\xff\xff");
            break;
        case Error:
            TransmitBufferAdd("Set.t2.txt=\"错误\"\xff\xff\xff");
            break;
        default:
            break;
        }
    }
}
